package org.jetlinks.community.mstn.service;

import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.authorization.DimensionProvider;
import org.hswebframework.web.crud.service.GenericReactiveCrudService;
import org.jetlinks.community.device.entity.DeviceInstanceEntity;
import org.jetlinks.community.mstn.entity.AssetsEntity;
import org.jetlinks.community.mstn.web.request.AssetsBindDeviceRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@Service
@AllArgsConstructor
public class AssetsService extends GenericReactiveCrudService<AssetsEntity, String> {

    private final List<DimensionProvider> providers;

    @Transactional
    public Mono<Void> bindDevice(Flux<AssetsBindDeviceRequest> deviceFlux) {
        return deleteDevice(deviceFlux)
                .flatMap(detail -> Flux
                    .fromIterable(providers)
                    .flatMap(provider -> provider
                        .getAllType()
                        .filter(type -> type.getId().equals(detail.getTargetType()))//过滤掉不同的维度类型
                        .singleOrEmpty()
                        .flatMap(type -> provider.getDimensionById(type, detail.getTargetId()))
                        .flatMapIterable(detail::toEntity))
                    .switchIfEmpty(Flux.defer(() -> Flux.fromIterable(detail.toEntity())))
                    .distinct(AssetsEntity::getAssetId)
                    )
                .filter(e -> CollectionUtils.isNotEmpty(e.getPermission()))
                .as(this::save)
                .then();
    }

    @Transactional
    public Mono<Void> unbindDevice(Flux<AssetsBindDeviceRequest> deviceFlux) {
        return deleteDevice(deviceFlux).then();
    }

    /**
     * 删除旧的设备资产
     * @return deviceFlux
     */
    public Flux<AssetsBindDeviceRequest> deleteDevice(Flux<AssetsBindDeviceRequest> deviceFlux) {
        return deviceFlux
            .flatMap(
                detail -> createDelete()
                    .where(AssetsEntity::getAssetTarget, detail.getTargetId())
                    .and(AssetsEntity::getAssetTargetType, detail.getTargetType())
                    .and(AssetsEntity :: getAssetType, detail.getAssetType())
                    .in(AssetsEntity ::getAssetId, detail.getAssetIdList())
                    .execute()
                    .thenReturn(detail));
    }


}